<?php
namespace Common\Model;

use  Think\Model;

class TokenModel extends Model
{
  protected $autoCheckFields = false;
  //检查是否在微信环境下

  public function get_token($app_key)
  {
    $config = $this->get_weiqing_config();
    $this->config = $config;
    $cache_type = $this->get_cache_type();
    $key = "accesstoken:{$app_key}";

    switch ($cache_type) {
      case "mysql":
        $token = $this->get_mysql_token($key);
        break;
      case "redis":
        $token = $this->get_redis_token($key);
        break;
      case "memcache":
        $token = $this->get_memcache_token($key);
        break;
      default:
        return false;
        break;
    }
    $token = $this->iunserializer($token);
    return $this->check_token($token);
  }

  function get_weiqing_config()
  {
    $configfile = str_replace("\\", '/', dirname(__FILE__));
    $configfile = substr($configfile, 0, stripos($configfile, "addons/zjhj_wdds"));
    $this->IA_ROOT = $configfile;
    $configfile .= "data/config.php";
    require $configfile;
    return $config;
  }

  function get_cache_type()
  {
  	$cache_type = strtolower($this->config['setting']['cache']);

  	if (extension_loaded($cache_type)) {
  		$config = $this->config['setting'][$cache_type];
  		if (!empty($config['server']) && !empty($config['port'])) {
  			if ($cache_type == 'memcache') {
  				$cacher = new \Memcache();
  			} elseif ($cache_type == 'redis') {
  				$cacher = new \Redis();
  			}
  			$connect = $cacher->connect($config['server'], $config['port']);
  		}
  	}
  	if (empty($cacher) || empty($connect)) {
  		$cache_type = 'mysql';
  	}
  	return $cache_type;
  }

  function get_mysql_token($key)
  {
    $token = M('core_cache', $this->config['db']['master']['tablepre'])->where(array('key' => "{$key}"))->getField('value');
    return $token;
  }

  function get_redis_token($key)
  {
    static $redisobj;
    if (!extension_loaded('redis')) {
      return array();
    }
    if (empty($redisobj)) {
      $config = $this->config['setting']['redis'];
      $redisobj = new \Redis();
      try {
        if ($config['pconnect']) {
          $connect = $redisobj->pconnect($config['server'], $config['port']);
        } else {
          $connect = $redisobj->connect($config['server'], $config['port']);
        }
        if (!empty($config['auth'])) {
          $auth = $redisobj->auth($config['auth']);
        }
      } catch (\Exception $e) {
        return array();
      }
    }
    try {
      if ($redisobj->exists($this->cache_prefix($key))) {
        $data = $redisobj->get($this->cache_prefix($key));
        $data = $this->iunserializer($data);

        return $data;
      }
    } catch (\Exception $e) {
      return array();
    }

    return array();
  }

  function get_memcache_token($key)
  {
    static $memcacheobj;
    if (!extension_loaded('memcache')) {
      return error(1, 'Class Memcache is not found');
    }
    if (empty($memcacheobj)) {
      $config = $this->config['setting']['memcache'];
      $memcacheobj = new \Memcache();
      if($config['pconnect']) {
        $connect = $memcacheobj->pconnect($config['server'], $config['port']);
      } else {
        $connect = $memcacheobj->connect($config['server'], $config['port']);
      }
      if(!$connect) {
        return error(-1, 'Memcache is not in work');
      }
    }

  	$memcache = $memcacheobj;
  	if ($this->is_error($memcache)) {
  		return array();
  	}
  	$result = $memcache->get($this->cache_prefix($key));
  	if (empty($result) || !$result) {
  		$result = get_mysql_token($key);
  	}
  	return $result;
  }

  function check_token($token)
  {
    if (!empty($token) && !empty($token['token']) && $token['expire'] > gmtime()) {
      $now_time = date("Y-m-d H:i:s",time());
      file_put_contents('wechat-token.log', "\r\n {$now_time} 读取微擎{$this->get_cache_type()}: {$token['token']}", FILE_APPEND);
      $token['access_token'] = $token['token'];
      return $token;
    } else {
      return false;
    }
  }

  ## 解析微擎数据库中的token
  function iunserializer($value)
  {
  	if (empty($value)) {
  		return array();
  	}
  	if (!$this->is_serialized($value)) {
  		return $value;
  	}
  	$result = unserialize($value);
  	if ($result === false) {
  		$temp = preg_replace_callback('!s:(\d+):"(.*?)";!s', function ($matchs){
  			return 's:'.strlen($matchs[2]).':"'.$matchs[2].'";';
  		}, $value);
  		return unserialize($temp);
  	} else {
  		return $result;
  	}
  }

  function is_serialized($data, $strict = true)
  {
  	if (!is_string($data)) {
  		return false;
  	}
  	$data = trim($data);
  	if ('N;' == $data) {
  		return true;
  	}
  	if (strlen($data) < 4) {
  		return false;
  	}
  	if (':' !== $data[1]) {
  		return false;
  	}
  	if ($strict) {
  		$lastc = substr($data, -1);
  		if (';' !== $lastc && '}' !== $lastc) {
  			return false;
  		}
  	} else {
  		$semicolon = strpos($data, ';');
  		$brace = strpos($data, '}');
  				if (false === $semicolon && false === $brace)
  			return false;
  				if (false !== $semicolon && $semicolon < 3)
  			return false;
  		if (false !== $brace && $brace < 4)
  			return false;
  	}
  	$token = $data[0];
  	switch ($token) {
  		case 's' :
  			if ($strict) {
  				if ('"' !== substr($data, -2, 1)) {
  					return false;
  				}
  			} elseif (false === strpos($data, '"')) {
  				return false;
  			}
  				case 'a' :
  		case 'O' :
  			return (bool)preg_match("/^{$token}:[0-9]+:/s", $data);
  		case 'b' :
  		case 'i' :
  		case 'd' :
  			$end = $strict ? '$' : '';
  			return (bool)preg_match("/^{$token}:[0-9.E-]+;$end/", $data);
  	}
  	return false;
  }

  function cache_prefix($key) {
  	return $this->config['setting']['authkey'] . $key;
  }

  function error($errno, $message = '') {
  	return array(
  		'errno' => $errno,
  		'message' => $message,
  	);
  }

  function is_error($data) {
  	if (empty($data) || !is_array($data) || !array_key_exists('errno', $data) || (array_key_exists('errno', $data) && $data['errno'] == 0)) {
  		return false;
  	} else {
  		return true;
  	}
  }
}
